/**
 * Copyright 2005 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.edi.client.param;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;

import com.edi.Constant;
import com.edi.db.EdiDb;
import com.edi.db.PreparedEql;
import com.edi.db.dao.EdiDAOException;
import com.edi.db.manager.DBManager;
import com.edi.db.table.TableEntity;
import com.edi.exceptions.EdiParamException;
import com.edi.util.StringHelper;

/**
 * EdiEPOClientParam 处理客户端EPO类型的请求
 * 
 * 
 */
public class EdiEPOClientParam extends EdiClientParam {

	private static final Log log = LogFactory.getLog(EdiEPOClientParam.class);

	private String METHODS_QUERY = "query";
	private String METHODS_EXEC = "exec";
	private String eql;
	private List<EqlParam> eqlParams;
	private List<FixTable> fixTables;
	private String currentPage; //前台传过来的当前页码

	public EdiEPOClientParam(Element ediPara) {
		super(ediPara);

		currentPage = ediPara.elementText("currentPage");

		pageSize = ediPara.elementText("pageSize");

		totalSize = ediPara.elementText("totalSize");

		this.transaction = ediPara.elementText("transaction");

		eql = ediPara.elementText("eql");

		eql = StringUtils.lowerCase(eql);

		eqlParams = new ArrayList<EqlParam>();
		List<Element> paramList = ediPara.element("parameters").elements(
				"param");
		for (Element paramE : paramList) {
			EqlParam eqlParam = new EqlParam();
			eqlParam.index = Integer.parseInt(paramE.attributeValue("index"));
			eqlParam.paramType = paramE.attributeValue("type");
			String paramValue = paramE.getText();

			log.debug("paramValue = " + paramValue);
			eqlParam.paramValue = paramValue;
			eqlParams.add(eqlParam);
		}
		//----------------尝试初始化混合表配置------------------//
		if (ediPara.element("fixTables") != null) {
			fixTables = new ArrayList<FixTable>();
			List<Element> fixTablesE = ediPara.element("fixTables").elements(
					"fixTable");
			for (Element fixTableE : fixTablesE) {
				FixTable fixTable = new FixTable(fixTableE);
				fixTables.add(fixTable);
			}
		}
	}

	public PreparedEql generPreparedEql() throws EdiParamException {
		PreparedEql preparedEql = new PreparedEql(eql);
		if (StringUtils.isNotBlank(currentPage))
			preparedEql.setCurrentPage(new Integer(currentPage));
		if (StringUtils.isNotBlank(pageSize))
			preparedEql.setPageSize(new Integer(pageSize));
		for (EqlParam eqlParam : eqlParams) {
			eqlParam.readToPreparedEql(preparedEql);
		}
		return preparedEql;
	}

	public void excuteClientParam() throws EdiParamException {
		PreparedEql preparedEql = generPreparedEql();

		log.debug("eql : " + this.eql);
		DBManager dbManager = new DBManager(Constant.SERVER_APPNAME);
		if (StringUtils.isBlank(methods)
				|| StringUtils.equalsIgnoreCase(methods, "null")) {
			if (StringUtils.startsWithIgnoreCase(eql, "select"))
				methods = METHODS_QUERY;
			else
				methods = METHODS_EXEC;
		}

		if (methods.equalsIgnoreCase(METHODS_QUERY)) {
			try {
				log.debug(" totalSize =" + totalSize);
				log.debug(" currentPage =" + currentPage);
				log.debug(" pageSize =" + pageSize);
				if (StringUtils.isNotBlank(currentPage)
						&& StringUtils.isNotBlank(pageSize)
						&& (totalSize == null || "".equals(totalSize))) {

					//第一次查询总记录数，下次不用再查询记录数，直接从前台获取
					int totalCount = this.getCount(eql);
					log.debug(" totalCount =" + totalCount);
					totalSize = String.valueOf(totalCount);
				}
				if (StringUtils.isNotBlank(pageSize)
						&& StringUtils.isNotBlank(totalSize)) {
					int intTotalSize = new Integer(totalSize).intValue();
					int intPageSize = new Integer(pageSize).intValue();
					int intTotalPage = StringHelper.getTotalPage(intPageSize,
							intTotalSize);
					this.totalPage = new Integer(intTotalPage);
					log.debug(" intTotalPage =" + intTotalPage);
				}
				returnTable = dbManager.queryPreparedEql(preparedEql);
				if (fixTables != null)
					for (FixTable fixTable : this.fixTables) {
						fixTable.toFix(returnTable);
					}
				state = Constant.EXEC_STATE_SUCESS;
			} catch (Exception e) {
				e.printStackTrace();
				state = Constant.EXEC_STATE_ERROR;
				errorMessage.append("EPO occured error: ");
				errorMessage.append(e.getMessage());
				log.error(e.getMessage());
				throw new EdiParamException("EPO occured error: ", e);
			}
		} else {
			try {
				dbManager.executePreparedEql(preparedEql);
				state = Constant.EXEC_STATE_SUCESS;
			} catch (Exception e) {
				e.printStackTrace();
				state = Constant.EXEC_STATE_ERROR;
				errorMessage.append("EPO occured error: ");
				errorMessage.append(e.getMessage());
				log.error(e.getMessage());
				throw new EdiParamException("EPO occured error: ", e);
			}
		}

	}

	/**
	 * 根据查询eql返回记录数查询eql
	 * 
	 * @param eql
	 * @return
	 */
	private String getCountQueryFromEql(String eql) {
		String returnEql = "select count(*) totalcount ";
		int fromIndex = eql.indexOf(" from ");
		log.debug(" fromIndex =" + fromIndex);
		returnEql += eql.substring(fromIndex);
		log.debug("fromIndex returnEql =" + returnEql);
		int groupIndex = returnEql.indexOf(" group ");
		log.debug(" groupIndex =" + groupIndex);
		if (groupIndex > 0)
			returnEql = returnEql.substring(0, groupIndex);
		log.debug("groupIndex returnEql =" + returnEql);
		int orderIndex = returnEql.indexOf(" order ");
		log.debug(" orderIndex =" + orderIndex);
		if (orderIndex > 0)
			returnEql = returnEql.substring(0, orderIndex);
		log.debug("orderIndex returnEql =" + returnEql);
		return returnEql;
	}

	private int getCount(String eql) throws EdiParamException, EdiDAOException {
		int count = 0;
		DBManager dbManager = new DBManager(Constant.SERVER_APPNAME);
		String countEql = getCountQueryFromEql(eql);
		log.debug("countEql =" + countEql);
		PreparedEql preparedEql = new PreparedEql(countEql);
		for (EqlParam eqlParam : eqlParams) {
			eqlParam.readToPreparedEql(preparedEql);
		}
		TableEntity table = dbManager.queryPreparedEql(preparedEql);
		count = table.getRow(0).getInt("totalcount");
		return count;
	}

	/**
	 * 处理返回的tableEntity
	 * 
	 * @return
	 */
	//	private void reBuildTable(TableEntity table){
	//		log.debug(" enter reBuildTable ");
	//		for(ServiceParameter serviceParam:serviceParamList){
	//			String associateS=serviceParam.getAssociateSource();
	//			String associateT=serviceParam.getAssociateTarget();	 
	//			log.debug(" associateS ="+associateS);
	//			log.debug(" associateT ="+associateT);
	//			for(RowEntity row:table.getRows()){
	//				Object associateSValue=row.getValue(associateS);
	//				log.debug("associateSValue ="+associateSValue);
	//				for(ColumnCell cell:row.getColumnCells().values()){
	//					String cellName=cell.getFieldName(); 
	//					String targetName=serviceParam.getMapFields().get(cellName);
	//					log.debug(" cellName ="+cellName);
	//					log.debug(" targetName ="+targetName);
	//					if(targetName!=null){  
	//						cell.setFieldName(targetName);	//替换表格单元名称
	//						log.debug(" serviceParam.getTableList() ="+serviceParam.getTableList().size());
	//						//替换单元格值
	//						for(TableEntity innerTable:serviceParam.getTableList()){
	//							Iterator<RowEntity> innerRowIt=innerTable.getRows().iterator();
	//							while(innerRowIt.hasNext()){
	//								RowEntity innerRow=innerRowIt.next();
	//								Object associateTValue=innerRow.getValue(associateT);
	//								log.debug("associateTValue = "+associateTValue);
	//								boolean flg=associateTValue.equals(associateSValue);
	//								log.debug("associateTValue.equals(associateSValue) ="+flg);
	//									if(flg){
	//										log.debug(" value ="+innerRow.getCell(targetName).getFieldValue());
	//										cell.setFieldValue(innerRow.getCell(targetName).getFieldValue());
	//										cell.setFieldType(innerRow.getCell(targetName).getFieldType()); 
	//									}
	////									innerRowIt.remove(); //删除掉已经替换过的行
	////								break;				//跳出循环
	//							} 
	//						}
	//					}
	//				}
	//			} 
	//		}
	//		log.debug(" end reBuildTable ");
	//	}

	/**
	 * 内嵌类，记录eql的param
	 * 
	 * @author 红木
	 * 
	 */
	private class EqlParam {
		public int index;
		public String paramType;
		public String paramValue;

		public void readToPreparedEql(PreparedEql preparedEql)
				throws EdiParamException {

			if (paramType.equalsIgnoreCase(EdiDb.TYPE_BOOLEAN)) {
				preparedEql.setBoolean(index, paramValue.equalsIgnoreCase("1"));
			} else if (paramType.equalsIgnoreCase(EdiDb.TYPE_DATE)) {
				try {
					preparedEql.setDateTime(index, DateUtils.parseDate(
							paramValue, Constant.simpleDateFormate));
				} catch (ParseException e) {
					throw new EdiParamException("日期转换错误：", e);
				}
			} else if (paramType.equalsIgnoreCase(EdiDb.TYPE_CURRENCY)) {
				preparedEql.setCurrency(index, new BigDecimal(paramValue));
			} else if (paramType.equalsIgnoreCase(EdiDb.TYPE_FLOAT)) {
				preparedEql.setFloat(index, Float.parseFloat(paramValue));
			} else if (paramType.equalsIgnoreCase(EdiDb.TYPE_INT)) {
				preparedEql.setInt(index, Integer.parseInt(paramValue));
			} else if (paramType.equalsIgnoreCase(EdiDb.TYPE_STRING)) {
				preparedEql.setString(index, paramValue);
			} else if (paramType.equalsIgnoreCase(EdiDb.TYPE_TEXT)) {
				preparedEql.setText(index, paramValue);
			} else
				preparedEql.setText(index, paramValue);
		}
	}
}
